package com.xxxx.car.audit.service.impl;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xxxx.car.appointment.domain.ServiceItem;
import com.xxxx.car.appointment.enums.ServiceItemAuditStatusEnum;
import com.xxxx.car.appointment.mapper.ServiceItemMapper;
import com.xxxx.car.appointment.vo.ServiceItemVo;
import com.xxxx.car.audit.enums.BpmnTypeEnum;
import com.xxxx.car.audit.enums.CarPackageAuditStatusEnum;
import com.xxxx.car.audit.vo.HandleAuditParam;
import com.xxxx.car.audit.vo.PackageAuditVo;
import com.xxxx.car.common.enums.BusinessStatus;
import com.xxxx.car.common.utils.DateUtils;
import com.xxxx.car.common.utils.PageUtils;
import com.xxxx.car.common.utils.SecurityUtils;
import com.xxxx.car.flow.domain.BpmnInfo;
import com.xxxx.car.flow.mapper.BpmnInfoMapper;
import com.xxxx.car.flow.service.impl.ProcessServiceImpl;
import io.jsonwebtoken.lang.Assert;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;
import com.xxxx.car.audit.mapper.PackageAuditMapper;
import com.xxxx.car.audit.domain.PackageAudit;
import com.xxxx.car.audit.service.IPackageAuditService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

/**
 * 审核信息Service业务层处理
 * 
 * @author Huang
 * @date 2024-10-11
 */
@Service
public class PackageAuditServiceImpl implements IPackageAuditService 
{
    @Resource
    private PackageAuditMapper packageAuditMapper;
    @Resource
    private ServiceItemMapper serviceItemMapper;
    @Resource
    private ProcessServiceImpl processService;
    @Resource
    private BpmnInfoMapper bpmnInfoMapper;

    /**
     * 查询审核信息
     * 
     * @param id 审核信息主键
     * @return 审核信息
     */
    @Override
    public PackageAudit selectPackageAuditById(Long id)
    {
        return packageAuditMapper.selectPackageAuditById(id);
    }

    /**
     * 查询审核信息列表
     * 
     * @param packageAudit 审核信息
     * @return 审核信息
     */
    @Override
    public List<PackageAudit> selectPackageAuditList(PackageAudit packageAudit)
    {
        return packageAuditMapper.selectPackageAuditList(packageAudit);
    }

    /**
     * 新增审核信息
     * 
     * @param packageAudit 审核信息
     * @return 结果
     */
    @Override
    public int insertPackageAudit(PackageAudit packageAudit)
    {
        packageAudit.setCreateTime(DateUtils.getNowDate());
        return packageAuditMapper.insertPackageAudit(packageAudit);
    }

    /**
     * 修改审核信息
     * 
     * @param packageAudit 审核信息
     * @return 结果
     */
    @Override
    public int updatePackageAudit(PackageAudit packageAudit)
    {
        return packageAuditMapper.updatePackageAudit(packageAudit);
    }

    /**
     * 批量删除审核信息
     * 
     * @param ids 需要删除的审核信息主键
     * @return 结果
     */
    @Override
    public int deletePackageAuditByIds(Long[] ids)
    {
        return packageAuditMapper.deletePackageAuditByIds(ids);
    }

    /**
     * 删除审核信息信息
     * 
     * @param id 审核信息主键
     * @return 结果
     */
    @Override
    public int deletePackageAuditById(Long id)
    {
        return packageAuditMapper.deletePackageAuditById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int startAudit(PackageAuditVo packageAuditVo) {
        ServiceItem serviceItem = serviceItemMapper.selectServiceItemById(packageAuditVo.getServiceItemId());
        Assert.notNull(serviceItem,"参数错误,找不到服务项");
        Assert.state(serviceItem.getIsMeal().equals(ServiceItemVo.IS_MEAL)
                && serviceItem.getSaleStatus().equals(ServiceItemVo.SALE_STATUS_NO)
                && (serviceItem.getAuditStatus() == ServiceItemAuditStatusEnum.INITIALING.ordinal()
                || serviceItem.getAuditStatus() == ServiceItemAuditStatusEnum.REJECTED.ordinal()),"此服务项不能开启审核");
        // 保存审核信息对象
        PackageAudit packageAudit = new PackageAudit();
        packageAudit.setServiceItemId(serviceItem.getId());
        packageAudit.setServiceItemName(serviceItem.getName());
        packageAudit.setServiceItemInfo(serviceItem.getRemark());
        // 折扣价
        packageAudit.setServiceItemPrice(serviceItem.getDiscountPrice());
        // UserId
        packageAudit.setCreatorId(String.valueOf(SecurityUtils.getUserId()));
        packageAudit.setInfo(packageAuditVo.getInfo());
        packageAudit.setStatus((long) CarPackageAuditStatusEnum.AUDITING.ordinal());
        packageAudit.setCreateTime(new Date());
        packageAuditMapper.insertPackageAudit(packageAudit);
        // 查询自己保存的bpmnInfo对象
        BpmnInfo bpmnInfo = bpmnInfoMapper.selectLastestBpmnInfoByType(BpmnTypeEnum.CAR_PACKAGE.ordinal());
        // 构建流程变量 (折扣金额 审核人 (店长&财务) )
        HashMap<String, Object> variables = new HashMap<>();
        // 转成既是整数,又是字符串
        variables.put("discountAmount",serviceItem.getDiscountPrice().longValue() + "");
        variables.put("shopOwnerId",packageAuditVo.getShopOwnerId());
        variables.put("financalId",packageAuditVo.getFinancialId());
        // 发起流程  (businessKey 就是通过 PackageAudit 的自增id设置的)
        String instanceId = processService.startProcessInstance(bpmnInfo.getProcessDefinitionKey(),
                String.valueOf(packageAudit.getId()),
                variables);
        // 更新套餐审核信息的流程实例id
        PackageAudit packageAuditNew = new PackageAudit();
        packageAuditNew.setId(packageAudit.getId());
        packageAuditNew.setInstanceId(instanceId);
        packageAuditMapper.updatePackageAudit(packageAuditNew);
        // 更新服务项的状态为审核中
        return serviceItemMapper.updateAuditStatus(serviceItem.getId(), ServiceItemAuditStatusEnum.AUDITING.ordinal());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int cancelAudit(Long id) {
        // 1. 基于 id 查询套餐信息
        PackageAudit audit = this.selectPackageAuditById(id);
        Assert.notNull(audit, "参数错误，套餐审核不存在");
        // 2. 判断状态只有审核中允许撤销
        Assert.state(CarPackageAuditStatusEnum.AUDITING.ordinal() == audit.getStatus(), "只有审核中才允许撤销");
        // 3. 更新套餐审核状态为撤销审核
        packageAuditMapper.updateStatus(id, CarPackageAuditStatusEnum.CANCEL.ordinal());
        // 4. 删除流程实例
        processService.deleteProcessInstance(audit.getInstanceId(), "[" + SecurityUtils.getUsername() + "]撤销审核");
        // 5. 更新服务项状态为初始化
        serviceItemMapper.updateAuditStatus(audit.getServiceItemId(), ServiceItemAuditStatusEnum.INITIALING.ordinal());
        return 1;
    }

    @Override
    public List<PackageAudit> selectAuditTodoList() {
        // 1.得到流程定义信息对象 (流程定义 key , 流程定义版本)
        BpmnInfo bpmnInfo = bpmnInfoMapper.selectLastestBpmnInfoByType(BpmnTypeEnum.CAR_PACKAGE.ordinal());
        // 2.通过activiti api 查询业务标识列表
        List<String> businessKeyList = processService.selectBusinessKeyList(bpmnInfo.getProcessDefinitionKey(),
                SecurityUtils.getUserId());
        // 如果查不到业务标识, 返回空数据
        if(CollectionUtils.isEmpty(businessKeyList)){
            return Collections.emptyList();
        }
        // 开始分页
        PageUtils.startPage();
        // 3.通过业务标识列表查到审核信息列表
        return packageAuditMapper.selectCarPackageAuditByIds(businessKeyList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void handleAudit(HandleAuditParam param) {
        // 1.基于套餐 id 查询套餐对象,得到流程实例id
        PackageAudit packageAudit = packageAuditMapper.selectPackageAuditById(param.getAuditId());
        Assert.notNull(packageAudit,"参数错误,审核对象不存在");
        Assert.state(CarPackageAuditStatusEnum.AUDITING.ordinal() == packageAudit.getStatus(),"非法状态");
        // 2.Activiti Api 处理任务
        // 如果是空为true 如果非空为false
        boolean completed = processService.handleTaskByInstanceIdAndAssignee(
                packageAudit.getInstanceId(),
                SecurityUtils.getUserId(),
                param);
        if(completed){
            // 套餐信息: 基于提交的审核状态,更新为通过或拒绝
            packageAuditMapper.updateStatus(param.getAuditId(),
                    param.isPassed() ? CarPackageAuditStatusEnum.PASSED.ordinal() : CarPackageAuditStatusEnum.REJECTED.ordinal());
            // 服务项: 基于提交的审核状态,更新为通过或拒绝
            serviceItemMapper.updateAuditStatus(packageAudit.getServiceItemId(),
                    param.isPassed() ? ServiceItemAuditStatusEnum.PASSED.ordinal() : ServiceItemAuditStatusEnum.REJECTED.ordinal());
        }
    }

    @Override
    public List<PackageAudit> selectAuditDoneList() {
        // 1.根据类型查询最新的流程信息对象
        BpmnInfo bpmnInfo = bpmnInfoMapper.selectLastestBpmnInfoByType(BpmnTypeEnum.CAR_PACKAGE.ordinal());
        // 2.通过Activiti API 查询 businessKey 集合
        Long userId = SecurityUtils.getUserId();
        List<String> businessKeyList = processService.selectHistoryBusinessKeyList(bpmnInfo.getProcessDefinitionKey(),userId,PackageAudit.DONE_LIST);
        if(CollectionUtils.isEmpty(businessKeyList)){
            return Collections.emptyList();
        }
        // 3.根据 businessKey 集合查询套餐信息列表
        return packageAuditMapper.selectCarPackageAuditByIds(businessKeyList);
    }

    @Override
    public List<PackageAudit> selectAuditListByType(String type) {
        // 1.根据类型查询最新的流程信息对象
        BpmnInfo bpmnInfo = bpmnInfoMapper.selectLastestBpmnInfoByType(BpmnTypeEnum.CAR_PACKAGE.ordinal());
        // 2.通过Activiti API 查询 businessKey 集合
        Long userId = SecurityUtils.getUserId();
        List<String> businessKeyList = processService.selectHistoryBusinessKeyList(bpmnInfo.getProcessDefinitionKey(),userId,type);
        if(CollectionUtils.isEmpty(businessKeyList)){
            return Collections.emptyList();
        }
        // 开始分页
        PageUtils.startPage();
        // 3.根据 businessKey 集合查询套餐信息列表
        return packageAuditMapper.selectCarPackageAuditByIds(businessKeyList);
    }
}
